package com.qf.listener;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.config.DelayedConfig;
import com.qf.constant.CacheConstants;
import com.qf.constant.RabbitMQConstants;
import com.qf.fegin.CacheFegin;
import com.qf.model.StandardReport;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;

/**
 * 监听
 *
 * @author dell
 * @version V1.0
 * @Date 2022/6/2 17:28:22
 */
@Component
@Slf4j
public class PushSmsReportListener {

    @Resource
    private CacheFegin cacheFegin;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper; // jackson的执行类  进行 json 之间的转换

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //时间数组   单位 毫秒
    private Integer[] sendTTL = {0, 10000, 30000, 60000, 300000};

    /**
     * 队列  push_sms_report
     */
    @RabbitListener(queues = RabbitMQConstants.TOPIC_PUSH_SMS_REPORT)
    public void listenerPushSmsReport(Message message, Channel channel, StandardReport standardReport) throws IOException {


        try {
            //接口模块  之前发送消息的时候  发送的 standardSubmit  就有分布式ID

            // 接口模块  接受之前的短信报告

            //StandardReport  唯一的序列标识   证明之前接收的 standardSubmit 报告

            //  推送报告给用户
            //  用户是否需要推送
            long clientID = standardReport.getClientID();
            Map map = cacheFegin.hMGet(CacheConstants.CACHE_PREFIX_CLIENT + clientID);
            if (!"1".equals(String.valueOf(map.get("isreturnstatus")))) {
                //客户表示  不让发推送报告  什么也不干  直接应答返回
                //手动应答
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }

            //需要推送报告   需要发推送报告
            Object receivestatusurl = map.get("receivestatusurl");
            standardReport.setReceiveStatusUrl(String.valueOf(receivestatusurl));
            String result = sendStatusReport(receivestatusurl, standardReport);
            if (null == result) {
                //手动应答
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            // 远程调用成功
            isSuccess(result, standardReport);


            //手动应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //e.printStackTrace();

            if (message.getMessageProperties().isRedelivered()) {
                //日志
                try {
                    log.error("接收推送用户的报告消息失败了 ： {}", objectMapper.writeValueAsString(standardReport));
                } catch (JsonProcessingException e1) {
                    e1.printStackTrace();
                }
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                //第一次接收消息
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

        }
    }

    /**
     * 判断远程调用  返回值是否成功 还是失败
     *
     * @param result
     */
    private void isSuccess(String result, StandardReport standardReport) {
        if (!"SUCCESS".equalsIgnoreCase(result)) {
            //失败
            // 重新发送报告  延时消息队列

            rabbitTemplate.convertAndSend(DelayedConfig.DELAYED_EXCHANGE, "routingKey", message -> {

                //延迟时间   通过发送的次数 获取对应的延迟时间
                message.getMessageProperties().setDelay(sendTTL[standardReport.getSendCount()]);

                return message;
            });

        }
    }

    /**
     * 给用户推送报告
     */
    public String sendStatusReport(Object receivestatusurl, StandardReport standardReport) {
        String result = null;
        try {
            // 给用户推送报告 最多推送5次  需要判断当前第几次
            int sendCount = standardReport.getSendCount();
            if (sendCount >= 5) {
                // 打印日志 转人工处理
                // 调用人工接口

                log.error(
                        "用户推送报告已经推送5次以上 还是没有成功：报告是：{}",
                        objectMapper.writeValueAsString(standardReport)
                );
                return null;
            }
            // 追加 推送次数
            sendCount++;
            standardReport.setSendCount(sendCount);

            // 参数1  url

            // 参数2  请求对象
            HttpHeaders httpHeaders = new HttpHeaders();
            // 请求头中指定传递的参数 json 类型
            httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

            HttpEntity<String> httpEntity =
                    new HttpEntity<String>(objectMapper.writeValueAsString(standardReport), httpHeaders);
            // 参数3 响应类型
            result = restTemplate.postForObject(
                    String.valueOf(receivestatusurl)
                    , httpEntity, String.class);
        } catch (Exception e) {
            // 重新发送报告  延时消息队列

            rabbitTemplate.convertAndSend(DelayedConfig.DELAYED_EXCHANGE, "routingKey", message -> {

                //延迟时间   通过发送的次数 获取对应的延迟时间
                message.getMessageProperties().setDelay(sendTTL[standardReport.getSendCount()]);

                return message;
            });

            return null;
        }
        //  远程调用成功  返回值不一定成功  succes  成功   fail  失败
        return result;
    }

    /**
     * 接收延迟队列消息 重新给客户发送
     */
    @RabbitListener(queues = DelayedConfig.DELAYED_QUEUE)
    public void replayPushSmsReport(Message message, Channel channel, StandardReport standardReport) {

        // 用户推荐报告
        String result = sendStatusReport(standardReport.getReceiveStatusUrl(), standardReport);
        if (null == result) {
            try {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        try {
            //判断是否发送成功
            isSuccess(result, standardReport);
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



/*

    @RabbitListener(queues = RabbitMQConstants.TOPIC_PUSH_SMS_REPORT)
    public void receiverDelayMessage(String msg, Channel channel, Message message) throws IOException {

        //推送给第三方报告

        //手动应答
        //channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

    }
*/

}
